package cn.zyb.user.interceptor;

import cn.zyb.basic.annoation.PreAuthorize;
import cn.zyb.system.mapper.PermissionMapper;
import cn.zyb.user.domain.Logininfo;
import cn.zyb.user.jwt.JwtUtils;
import cn.zyb.user.jwt.LoginData;
import cn.zyb.user.jwt.Payload;
import cn.zyb.user.jwt.RsaUtils;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.PublicKey;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component //将当前类交给Spring管理 = 创建LoginInterceptor对象：1.配置类中注入  2.请求来了，要通过对象掉用非静态方法
public class LoginInterceptor implements HandlerInterceptor {

  @Autowired
  private PermissionMapper permissionMapper;

  @Autowired
  private RedisTemplate redisTemplate;

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //1.获取请求头中的token - jwt token
    String token = request.getHeader("token");
    //3.判断
    if(token != null){

      Logininfo logininfo = null;
      try {
        //获取公钥
        PublicKey publicKey = RsaUtils.getPublicKey(JwtUtils.class.getClassLoader().getResource("auth_rsa.pub").getFile());
        //解密之后获取载荷数据
        Payload<LoginData> payload = JwtUtils.getInfoFromToken(token, publicKey, LoginData.class);
        logininfo = payload.getLoginData().getLogininfo();
      } catch (ExpiredJwtException e) { //jwt过期时抛出的异常
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(" {\"success\":false,\"msg\":\"timeout\"}");
        return false;
      }

      //登录成功 - 验证权限
      //1.如果是前台用户 - 放行 - 前台用户不需要验证权限 - 没有权限和菜单
      if(logininfo.getType()==1){
        return true;
      }
      //2.如果是后台管理员 - 验证权限【先获取当前登录人的所有权限sn的集合 ，再获取当前接口方法上的注解里面的sn】
      HandlerMethod method = (HandlerMethod)handler; //你访问的是哪一个接口就是哪一个接口方法
      //获取接口上名称为PreAuthorize的注解
      PreAuthorize preAuthorize = method.getMethodAnnotation(PreAuthorize.class);
      if(preAuthorize==null){//当前接口没有这个注解 = 登录拦截中放行的接口 = 公共资源
        return true;
      }

      //验证
      //注解上的sn属性值
      String sn = preAuthorize.sn();
      //获取当前登录人的所有权限的sn组成的集合
      List<String> permissions = permissionMapper.loadPermissionSnByLogininfoId(logininfo.getId());
      if(permissions.contains(sn)){ //当前登录人有权限访问该接口
        return true;
      }

      response.setContentType("application/json;charset=UTF-8");
      response.getWriter().println(" {\"success\":false,\"msg\":\"noPermission\"}");
      return false;

    }

    //3.2.如果没有 = 没有登录/登陆过期 -> 响应给前端json数据 -> 前端判断并跳转
    //告诉浏览器我要给你响应一个json数据
    //json数据的格式要转换必须有一个要求：格式必须是标准格式：里面的字符串必须用双引号表示
    response.setContentType("application/json;charset=UTF-8");
    response.getWriter().println(" {\"success\":false,\"msg\":\"noLogin\"}");
    return false;
  }
}
